package cn.gov.mwr.sl330;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.StringUtils;


/**
 * 水情信息解析类
 *
 * @author lipujun
 * @ClassName: HydroParser
 * @Description: TODO
 * @date Mar 20, 2013
 */
public class HydroParser {

    /**
     * 降水量编码要素及标识符
     */
    private final static ConcurrentHashMap CODE_P = new ConcurrentHashMap();

    static {
        CODE_P.put("PN01", new Element("PN01", TypeData.NUMBER, ""));
        CODE_P.put("PN05", new Element("PN05", TypeData.NUMBER, ""));
        CODE_P.put("PN10", new Element("PN10", TypeData.NUMBER, ""));
        CODE_P.put("PN30", new Element("PN30", TypeData.NUMBER, ""));
        CODE_P.put("P1", new Element("P1", TypeData.NUMBER, ""));
        CODE_P.put("P2", new Element("P2", TypeData.NUMBER, ""));
        CODE_P.put("P3", new Element("P3", TypeData.NUMBER, ""));
        CODE_P.put("P6", new Element("P6", TypeData.NUMBER, ""));
        CODE_P.put("P12", new Element("P12", TypeData.NUMBER, ""));
        CODE_P.put("PD", new Element("PD", TypeData.NUMBER, ""));
        CODE_P.put("PX", new Element("PX", TypeData.NUMBER, ""));
        CODE_P.put("PM", new Element("PM", TypeData.NUMBER, ""));
        CODE_P.put("PR", new Element("PR", TypeData.NUMBER, ""));
        CODE_P.put("DT", new Element("DT", TypeData.NUMBER, ""));
        CODE_P.put("PHT", new Element("PHT", TypeData.NUMBER, ""));
        CODE_P.put("PHD", new Element("PHD", TypeData.NUMBER, ""));
        CODE_P.put("PSH", new Element("PSH", TypeData.NUMBER, ""));
        CODE_P.put("PSD", new Element("PSD", TypeData.NUMBER, ""));
        CODE_P.put("WS", new Element("WS", TypeData.NUMBER, ""));

    }

    /**
     * 人工置数处理逻辑
     *
     * @param info
     */
    public static List<HydroData> process(String info) {

        List<HydroData> result = new ArrayList<HydroData>();

        // 将字符串进行处理，去掉因人工输入误操作的多余“空格”
        if (StringUtils.isNotEmpty(info)) {
            while (info.indexOf("  ") != -1) {
                info = info.replaceAll("  ", " ");
            }
        }

        // 得到第一位编码分类码，并去掉报文结束标识符
        int s_pos = info.indexOf(Separator.SEP);
        int e_pos = info.indexOf(Separator.NN);

        String token = info.substring(0, s_pos);
        String data = info.substring(s_pos);
        if (e_pos != -1) {
            data = info.substring(s_pos, e_pos);
        }

        System.out.println(">>token\t " + token);
        System.out.println(">>data\t " + data);

        // 根据“编码分类码”，进行分析
        // 第一步：先进行多站分析
        String ST[] = data.split(Separator.ST);
        System.out.println(">>ST DATA LENGTH \t " + ST.length);
        for (int i = 0, len = ST.length; i < len; i++) {

            if (token.indexOf(Separator.C) != -1) {
                // 表示等距时间序列格式
                result.addAll(processCP(token, ST[i]));
            } else {
                // 处理多时间序列
                result.addAll(processST(token, ST[i]));
            }

        }

        return result;

    }

    /**
     * 处理“等距时间序列格式” 报文
     *
     * @param typeCode
     * @param info
     */
    public static List<HydroData> processCP(String typeCode, String info) {

        List<HydroData> list = new ArrayList<HydroData>();

        String data[] = StringUtils.trim(info).split(Separator.SEP);

        String stcd = data[0];
        String date = data[1];
        Date curDate = convertDate(date);
        String DR = data[2];
        String drx = DR.substring(2, 3);
        String drnn = DR.substring(3, 5);

        List<String> nameList = new ArrayList<String>();
        int pos = 0;

        // 查找有几个标识符
        for (int i = 3, len = data.length; i < len; i++) {
            if (CODE_P.containsKey(data[i])) {
                pos = pos + 1;
                nameList.add(data[i]);
            } else {
                break;
            }
        }

        // 开始解析数据
        for (int i = 3 + pos, len = data.length; i < len; i++) {

            List<HydroDataItem> items = new ArrayList<HydroDataItem>();

            for (int j = 0; j < pos; j++) {
                System.out.print(" " + nameList.get(j) + " " + data[i + j]
                        + "\t");

                HydroDataItem item = new HydroDataItem();
                item.setName(nameList.get(j));
                item.setValue(data[i + j]);
                items.add(item);

            }
            i = i + pos - 1;
            System.out.println(" ");

            HydroData itemInfo = new HydroData();
            itemInfo.setTypeCode(typeCode);
            itemInfo.setStcd(stcd);
            itemInfo.setViewDate(curDate);
            itemInfo.setItems(items);

            list.add(itemInfo);

            // 开始增加时间
            curDate = processDate(curDate, drx, drnn);

        }

        return list;

    }

    public static Date convertYYMMDDHHmmss(String viewDate) {

        SimpleDateFormat sdf2 = new SimpleDateFormat("yyMMddHHmmss");// "yyyy-MM-dd HH:mm:ss"

        Date curDate = null;
        try {
            curDate = sdf2.parse(viewDate);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return curDate;
    }

    public static Date convertYYMMDDHHmm(String viewDate) {

        SimpleDateFormat sdf2 = new SimpleDateFormat("yyMMddHHmm");// "yyyy-MM-dd HH:mm:ss"

        Date curDate = null;
        try {
            curDate = sdf2.parse(viewDate);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return curDate;
    }

    public static Date addMinYYMMDDHHmm(String viewDate, Integer step) {

        SimpleDateFormat sdf2 = new SimpleDateFormat("yyMMddHHmm");// "yyyy-MM-dd HH:mm:ss"

        Date curDate = null;
        try {
            curDate = sdf2.parse(viewDate);
            Calendar nowTime = Calendar.getInstance();
            nowTime.setTime(curDate);
            nowTime.add(Calendar.MINUTE, step);
            curDate = nowTime.getTime();
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return curDate;
    }

    /**
     * 转换时间，因为人工置数报的时间未添加年份，所以需要转换的时候添加年份
     *
     * @param viewDate
     * @return
     */
    public static Date convertDate(String viewDate) {
        // 时间上一定得加上今年的，要不然加出来的时间不正确
        SimpleDateFormat sdf = new SimpleDateFormat(TypeDate.YEAR);
        String year = sdf.format(new Date(System.currentTimeMillis()));
        viewDate = year + viewDate;

        SimpleDateFormat sdf2 = new SimpleDateFormat(TypeDate.FORMAT);// "yyyy-MM-dd HH:mm:ss"

        Date curDate = null;
        try {
            curDate = sdf2.parse(viewDate);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return curDate;
    }

    /**
     * 处理时间，针对等时段间距时间的添加
     *
     * @param viewDate
     * @param drx
     * @param drnn
     * @return
     */
    public static Date processDate(Date curDate, String drx, String drnn) {

        int amount = Integer.parseInt(drnn);
        if (drx.equalsIgnoreCase(TypeDate.D)) {
            return DateUtil.addDays(curDate, amount);
        }

        if (drx.equalsIgnoreCase(TypeDate.H)) {
            return DateUtil.addHours(curDate, amount);
        }

        if (drx.equalsIgnoreCase(TypeDate.N)) {
            return DateUtil.addMinutes(curDate, amount);
        }

        return curDate;
    }

    /**
     * 处理“测站”报文
     *
     * @param typeCode
     * @param info
     */
    public static List<HydroData> processST(String typeCode, String info) {

        List<HydroData> list = new ArrayList<HydroData>();

        String stInfo = info;
        if (StringUtils.isNotEmpty(stInfo)) {
            stInfo = StringUtils.trim(stInfo);
        }

        int st_pos = stInfo.indexOf(Separator.SEP);
        String st_token = stInfo.substring(0, st_pos);
        String st_data = stInfo.substring(st_pos);
        System.out.println(">>ST INFO \t " + st_token + " --- " + st_data);

        String TT[] = StringUtils.trim(st_data).split(Separator.TT);
        for (int i = 0, len = TT.length; i < len; i++) {
            if (StringUtils.isNotBlank(TT[i])) {
                HydroData itemInfo = new HydroData();
                itemInfo.setTypeCode(typeCode);
                itemInfo.setStcd(st_token);

                processTT(itemInfo, TT[i]);

                list.add(itemInfo);
            }
        }

        return list;

    }

    /**
     * 处理“多时间”报文
     *
     * @param hydro
     * @param info
     */
    public static void processTT(HydroData hydro, String info) {

        List<HydroDataItem> items = new ArrayList<HydroDataItem>();

        String ttInfo = info;
        if (StringUtils.isNotEmpty(ttInfo)) {
            ttInfo = StringUtils.trim(ttInfo);
        }

        int tt_pos = ttInfo.indexOf(Separator.SEP);
        String viewDate = ttInfo.substring(0, tt_pos);
        String tt_data = ttInfo.substring(tt_pos);

        hydro.setViewDate(convertDate(viewDate));

        System.out.println(">>----TT  \t " + viewDate + " --- " + tt_data);
        String data[] = StringUtils.trim(tt_data).split(Separator.SEP);
        for (int i = 0, len = data.length; i < len; i++) {
            HydroDataItem item = new HydroDataItem();
            item.setName(data[i]);
            i = i + 1;
            item.setValue(new Double(data[i]));
            items.add(item);

            System.out.println(">>>>TT item \t " + item.getName() + " --- "
                    + item.getValue());

        }

        hydro.setItems(items);

    }

    /**
     * 人工置数“降水量编码”
     */
    public static void parseRgzsP(String message) {

        String[] data = StringUtils.split(message, Separator.SEP);

        String typeCode = data[0];
        String stcd = data[1];
        String viewDate = data[2];

        HydroData info = new HydroData();
        info.setTypeCode(typeCode);
        info.setStcd(stcd);
        info.setViewDate(convertDate(viewDate));

        List<HydroDataItem> items = new ArrayList();

        int pos = 3;
        // 表示为等距时段数据报
        if (typeCode.indexOf("C") != -1) {

        } else {

            for (int i = pos, len = data.length; i < len; i++) {

                String itemName = data[pos];
                i++;
                String itemValue = data[pos];

                if (itemName.equalsIgnoreCase("TT")) {
                    // 表示，同一测站中不同观测时间的数据

                } else if (itemName.equalsIgnoreCase("ST")) {
                    // 表示，发送多个测站的数据

                } else {

                }

                HydroDataItem item = new HydroDataItem();
                item.setName(itemName);
                item.setValue(new Double(itemValue));
                items.add(item);

                if ((i + 2) > len) {
                    break;
                }

            }
        }

    }

    /**
     * 人工置数“河道水情”
     */
    public static void parseRgzsH(String data) {

    }

    /**
     * 人工置数“水库（湖泊）”
     */
    public static void parseRgzsK(String data) {

    }

    /**
     * 人工置数“闸坝”
     */
    public static void parseRgzsZ(String data) {

    }

    /**
     * 人工置数“泵站”
     */
    public static void parseRgzsD(String data) {

    }

    /**
     * 人工置数“潮汐”
     */
    public static void parseRgzsT(String data) {

    }

    /**
     * 人工置数“土壤墒情”
     */
    public static void parseRgzsM(String data) {

    }

    /**
     * 人工置数“地下水情”
     */
    public static void parseRgzsG(String data) {

    }

    /**
     * 人工置数“水文预报”
     */
    public static void parseRgzsF(String data) {

    }

    public static void main(String[] args) {
        String info = "P 11110000 09090900 P1 10.9 WS 8 TT 09011000 P1 19 WS 8 NN";

        info = "P 11110000 08151400 P6 78.2 WS 9 ST 51005000 08151400 P6 98.6 WS 8 NN";

        // info = "CP 11110000 09010900 DRH01 P1 WS " + "10.9 8 " + "19 8 "
        // + "5 9 " + "14 7 " + "5.6 8 " + "8.9 8 " + "7 8 " + "12.5 7 "
        // + "M 8 " + "7.7 8 NN";

        List<HydroData> result = HydroParser.process(info);
        for (int i = 0, len = result.size(); i < len; i++) {

            HydroData data = result.get(i);
            System.out.println(data);

        }

        String tt = "TT";
        System.out.println("length >> " + tt.getBytes().length);

        //

    }

}
